﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Input;

namespace Draco.OWF.Studio.Utility
{
    public delegate void ElementMoveEventHandler(object sender, ElementMoveEventArgs e);
    public class ElementMoveWrapper
    {
        private bool m_isMouseLeftButtonDown=false;
        private bool m_Moving = false;
        private MouseButtonEventArgs m_MouseDownEvent;//for click judge
        private int ClickTimeSpan = 100;
        private UIElement m_ReferenceElement=null;
        
        public UIElement WrapperElement { get; private set; }
        public Point PreviousMousePoint { get; private set; }
        public Point StartMoveMousePoint { get; private set; }
        public event ElementMoveEventHandler ElementMoveStart;
        public event ElementMoveEventHandler ElementMoving;
        public event ElementMoveEventHandler ElementMoveComplete;
        public event MouseButtonEventHandler ElementLeftClick;
        public event MouseButtonEventHandler ElementRightClick;

        /// <summary>
        /// constructor
        /// </summary>
        /// <param name="element"></param>
        public ElementMoveWrapper(UIElement element, UIElement referenceElement)
        {
            this.WrapperElement = element;
            this.m_ReferenceElement = referenceElement;
            WrapElement();
        }

        private void WrapElement()
        {
            WrapperElement.MouseLeftButtonDown += new MouseButtonEventHandler(WrapperElement_MouseLeftButtonDown);
            WrapperElement.MouseMove += new MouseEventHandler(WrapperElement_MouseMove);
            WrapperElement.MouseLeftButtonUp += new MouseButtonEventHandler(WrapperElement_MouseLeftButtonUp);

            WrapperElement.MouseRightButtonDown += new MouseButtonEventHandler(WrapperElement_MouseRightButtonDown);
            WrapperElement.MouseRightButtonUp += new MouseButtonEventHandler(WrapperElement_MouseRightButtonUp);
        }

        #region Right click
        void WrapperElement_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            this.m_MouseDownEvent = e;
        }
        void WrapperElement_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (e.GetPosition(m_ReferenceElement) == this.m_MouseDownEvent.GetPosition(m_ReferenceElement))
            {
                if (e.Timestamp - this.m_MouseDownEvent.Timestamp < this.ClickTimeSpan)//clicked
                {
                    if (this.ElementRightClick != null)
                        this.ElementRightClick(sender,e);
                }
            }
        }
        #endregion

        #region Left click and move
        void WrapperElement_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            this.m_MouseDownEvent = e;
            this.PreviousMousePoint = e.GetPosition(m_ReferenceElement);
            this.StartMoveMousePoint = e.GetPosition(m_ReferenceElement); 
            this.m_isMouseLeftButtonDown = true;
            e.Handled = true;//it is import here
        }
        void WrapperElement_MouseMove(object sender, MouseEventArgs e)
        {
            UIElement ele = sender as UIElement;
            if (ele == null || ele != WrapperElement)
            {
                return;
            }
            if (this.m_isMouseLeftButtonDown && e.LeftButton == MouseButtonState.Pressed)//move
            {
                Point PositionNow = e.GetPosition(m_ReferenceElement);
                ElementMoveEventArgs arg = new ElementMoveEventArgs(e, this.StartMoveMousePoint, PreviousMousePoint, PositionNow);

                if (!this.m_Moving)//first move
                {
                    this.m_Moving = true;
                    WrapperElement.CaptureMouse();
                    if (this.ElementMoveStart != null)
                    {
                        ElementMoveStart(sender, arg);
                    }
                }
                //Moving
                if (ElementMoving != null)
                {
                    ElementMoving(sender, arg);
                    this.PreviousMousePoint = PositionNow;
                }
            }
        }
        void WrapperElement_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (this.m_Moving)//last moved
            {
                this.m_Moving = false;
                if (this.ElementMoveComplete != null)
                {
                    Point PositionNow = e.GetPosition(m_ReferenceElement);
                    ElementMoveComplete(sender, new ElementMoveEventArgs(e, this.StartMoveMousePoint, PreviousMousePoint, PositionNow));
                }
            }
            else   // only click
            {
                if (this.m_MouseDownEvent!=null && e.Timestamp - this.m_MouseDownEvent.Timestamp < this.ClickTimeSpan)//clicked
                {
                    if (this.ElementLeftClick != null)
                        this.ElementLeftClick(sender, e);
                }
            }
            WrapperElement.ReleaseMouseCapture();
            this.m_isMouseLeftButtonDown = false;
        }
        #endregion
    }
    public class ElementMoveEventArgs
    {
        public MouseEventArgs MouseEventArgs { get; private set; }
        public Point StartMousePoint { get; private set; }
        public Point PreviousMousePoint { get; private set; }
        public Point CurrentMousePoint { get; private set; }
        public double DeltaX { get; private set; }
        public double DeltaY { get; private set; }

        public ElementMoveEventArgs(MouseEventArgs arg, Point startMousePoint, Point previousMousePoint, Point currentMousePoint)
        {
            MouseEventArgs = arg;
            StartMousePoint = startMousePoint;
            PreviousMousePoint = previousMousePoint;
            CurrentMousePoint = currentMousePoint;
            DeltaX = CurrentMousePoint.X - PreviousMousePoint.X;
            DeltaY = CurrentMousePoint.Y - PreviousMousePoint.Y;
        }
    }
}
